package com.hyt.it.ogt.kq.service.gov.service.impl;

import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.hyt.core.base.BaseEntity;
import com.hyt.core.base.BaseServiceImpl;
import com.hyt.core.util.UUIDUtils;
import com.hyt.it.ogt.kq.common.config.exception.KqException;
import com.hyt.it.ogt.kq.common.gov.constant.CodeEnum;
import com.hyt.it.ogt.kq.common.gov.constant.ResponseCode;
import com.hyt.it.ogt.kq.common.gov.enums.TaskCandidateAreaVirtualAreaIdEnums;
import com.hyt.it.ogt.kq.service.gov.api.cj.model.TaskCandidateAreaVO;
import com.hyt.it.ogt.kq.service.gov.api.ks.model.CandidateAreaVO;
import com.hyt.it.ogt.kq.service.gov.feign.pt.GovPtClient;
import com.hyt.it.ogt.kq.service.gov.mapper.TaskCandidateAreaMapper;
import com.hyt.it.ogt.kq.service.gov.model.entity.TaskArea;
import com.hyt.it.ogt.kq.service.gov.model.entity.TimeRoomCandidate;
import com.hyt.it.ogt.kq.service.gov.model.excel.CandidateBmAreaSheet;
import com.hyt.it.ogt.kq.service.gov.model.excel.listener.CandidateBmAreaListener;
import com.hyt.it.ogt.kq.service.gov.model.vo.CandidateAreaListVO;
import com.hyt.it.ogt.kq.service.gov.model.vo.Tree;
import com.hyt.it.ogt.kq.service.gov.service.*;
import com.hyt.it.ogt.kq.service.model.entity.TaskCandidateArea;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 任务考生所属区域表 服务实现类
 * </p>
 *
 * @author huangyh
 * @since 2021-07-26
 */
@Service
public class TaskCandidateAreaServiceImpl extends BaseServiceImpl<TaskCandidateAreaMapper, TaskCandidateArea> implements ITaskCandidateAreaService {

    @Resource
    private IOfficeCandidateAreaService iOfficeCandidateAreaService;

    @Resource
    private ICandidateService iCandidateService;

    @Resource
    private ITimeRoomCandidateService iTimeRoomCandidateService;

    @Resource
    private GovPtClient govPtClient;

    @Resource
    private IOfficeAreaService iOfficeAreaService;

    @Override
    public List<TaskCandidateArea> getCandidateAreaProvince(String taskId) {
        //判断是否为自己定义过的

        return this.lambdaQuery()
                .eq(TaskCandidateArea::getTaskId, taskId)
                .eq(TaskCandidateArea::getType, CodeEnum.AREA_TYPE_PROVINCE.getCode())
                .eq(TaskCandidateArea::getDelFlag, false)
                .orderByAsc(TaskCandidateArea::getAreaId)
                .list();
    }

    @Override
    public List<TaskCandidateArea> getCandidateAreaCity(String taskId, String provinceId) {
        //判断是否为自己定义过的
        return this.lambdaQuery()
                .eq(TaskCandidateArea::getTaskId, taskId)
                .eq(TaskCandidateArea::getParentId, provinceId)
                .eq(TaskCandidateArea::getType, CodeEnum.AREA_TYPE_CITY.getCode())
                .eq(TaskCandidateArea::getDelFlag, false)
                .orderByAsc(TaskCandidateArea::getAreaId)
                .list();
    }

    @Override
    public List<TaskCandidateArea> getCandidateAreaDistrict(String taskId, String cityId) {
        //判断是否为自己定义过的
        return this.lambdaQuery()
                .eq(TaskCandidateArea::getTaskId, taskId)
                .eq(TaskCandidateArea::getParentId, cityId)
                .eq(TaskCandidateArea::getType, CodeEnum.AREA_TYPE_DISTRICT.getCode())
                .eq(TaskCandidateArea::getDelFlag, false)
                .orderByAsc(TaskCandidateArea::getAreaId)
                .list();
    }


    @Override
    public Map<String, TaskCandidateArea> getTaskCandidateArea(String taskId) {
        //判断是否为自己定义过的
        List<TaskCandidateArea> taskCandidateAreaList = this.lambdaQuery()
                .eq(TaskCandidateArea::getTaskId, taskId)
                .eq(TaskCandidateArea::getDelFlag, false)
                .select(TaskCandidateArea::getAreaId, TaskCandidateArea::getType, TaskCandidateArea::getParentId, TaskCandidateArea::getParentIds, TaskCandidateArea::getName)
                .list();
        Map<String, TaskCandidateArea> mapTaskCandidateArea = new HashMap<>(taskCandidateAreaList.size());
        taskCandidateAreaList.forEach(taskCandidateArea -> mapTaskCandidateArea.put(taskCandidateArea.getAreaId(), taskCandidateArea));
        return mapTaskCandidateArea;
    }

    @Override
    public List<TaskCandidateArea> getTaskCandidateAreaDistrictList(String taskId) {
        return this.lambdaQuery()
                .eq(TaskCandidateArea::getTaskId,taskId)
                .eq(TaskCandidateArea::getDelFlag,false)
                .eq(TaskCandidateArea::getType,4)
                .orderByAsc(TaskCandidateArea :: getParentIds )
                .select(TaskCandidateArea::getAreaId,TaskCandidateArea::getType,TaskCandidateArea::getParentId,TaskCandidateArea::getParentIds,TaskCandidateArea::getName)
                .list();

    }

    @Override
    public void initTaskCandidateArea(String taskId, String officeId) {

        Integer count = this.lambdaQuery()
                .eq(TaskCandidateArea::getTaskId,taskId)
                .eq(TaskCandidateArea::getDelFlag,false)
                .count();

        if (count <= 0) {

            //校验和初始化考生机构参数
            iOfficeCandidateAreaService.initOfficeCandidateArea(officeId);
            //初始化任务考生区域参数
            List<TaskArea> allAreaList = iOfficeAreaService.getAllAreaList();
            List<TaskCandidateArea> entitys = new ArrayList<>(allAreaList.size());
            for(TaskArea area : allAreaList){
                TaskCandidateArea entity = new TaskCandidateArea();
                BeanUtils.copyProperties(area,entity);
                entity.setId(UUIDUtils.newSortUUID());
                entitys.add(entity);
                entity.setTaskId(taskId);
                entity.setFullName(area.getFullName());
            }
            //baseMapper.initTaskCandidateArea(taskId,officeId);
            if(!CollectionUtils.isEmpty(entitys)){
                this.saveBatch(entitys);
            }
        }
    }

    @Override
    public List<TaskCandidateArea> listByTaskId(String taskId) {
        return this.lambdaQuery()
                .eq(TaskCandidateArea::getTaskId, taskId)
                .eq(TaskCandidateArea::getDelFlag, false)
                .list();
    }

    @Override
    public void deleteByTaskId(String taskId) {
        this.lambdaUpdate()
                .eq(TaskCandidateArea::getTaskId, taskId)
                .eq(TaskCandidateArea::getDelFlag, false)
                .set(TaskCandidateArea::getDelFlag, true)
                .update();
    }

    @Override
    public void initVirtualTaskCandidateArea(String taskId) throws KqException {

        Integer count = lambdaQuery()
                .eq(TaskCandidateArea::getTaskId,taskId)
                .eq(TaskCandidateArea::getDelFlag,false)
                .count();

        if (count > 0) {
            return;
        }

        List<TaskCandidateArea> taskCandidateAreaList = new ArrayList<>();
        //虚拟国
        TaskCandidateArea country = new TaskCandidateArea();
        country.setTaskId(taskId)
                .setAreaId("100000")
                .setName("虚拟国")
                .setType("1");
        taskCandidateAreaList.add(country);
        //虚拟省
        TaskCandidateArea province = new TaskCandidateArea();
        province.setTaskId(taskId)
                .setAreaId("100001")
                .setParentId("100000")
                .setParentIds("100000")
                .setName("虚拟省")
                .setType("2");
        taskCandidateAreaList.add(province);
        //虚拟市
        TaskCandidateArea city = new TaskCandidateArea();
        city.setTaskId(taskId)
                .setAreaId("100011")
                .setParentId("100001")
                .setParentIds("100000,100001")
                .setName("虚拟市")
                .setType("3");
        taskCandidateAreaList.add(city);
        //虚拟区县
        TaskCandidateArea district = new TaskCandidateArea();
        district.setTaskId(taskId)
                .setAreaId("100111")
                .setParentId("100011")
                .setParentIds("100000,100001,100011")
                .setName("虚拟区县")
                .setType("4");
        taskCandidateAreaList.add(district);
        /*if (!saveBatch(taskCandidateAreaList)) {
            throw new KqException(ResponseCode.CANDIDATE_AREA_ONLINE_INIT.getCode(),"虚拟考场初始化考生区域数据失败");
        }*/
    }

    @Override
    public CandidateAreaVO getVOByTaskId(String taskId, String timeId, String admissionNumber) {

        // 1.批次考生人数统计
        Integer timeCandidateCounts = iTimeRoomCandidateService.lambdaQuery()
                .eq(TimeRoomCandidate::getTaskId, taskId)
                .eq(TimeRoomCandidate::getTimeId, timeId)
                .eq(TimeRoomCandidate::getDelFlag, false)
                .count();

        // 2.考生报名的省市县区考点信息 - 保持原有逻辑
        CandidateAreaVO candidateAreaVO = iTimeRoomCandidateService.getCandidateAreaVO(taskId, timeId, admissionNumber);
        candidateAreaVO.setTimeCandidateCounts(timeCandidateCounts);
        return candidateAreaVO;

     /*   Optional<TimeRoomCandidate> timeRoomCandidateOptional = iTimeRoomCandidateService.lambdaQuery()
                .select(TimeRoomCandidate::getCandidateId)
                .eq(TimeRoomCandidate::getTaskId, taskId)
                .eq(TimeRoomCandidate::getTimeId, timeId)
                .eq(TimeRoomCandidate::getAdmissionNum, admissionNumber)
                .eq(TimeRoomCandidate::getDelFlag, false)
                .last("LIMIT 1")
                .oneOpt();
        timeRoomCandidateOptional.map(timeRoomCandidate -> {
            Optional<Candidate> candidateOptional = iCandidateService.lambdaQuery()
                    .select(Candidate::getProvince, Candidate::getCity, Candidate::getDistrict)
                    .eq(Candidate::getTaskId, taskId)
                    .eq(Candidate::getId, timeRoomCandidate.getCandidateId())
                    .eq(Candidate::getDelFlag, false)
                    .last("LIMIT 1")
                    .oneOpt();
            candidateOptional.map(candidate -> {
                BeanUtils.copyProperties(candidate, candidateAreaVO);

            }).orElse(null);
        }).orElse(null);
*/
    }

    @Override
    public List<TaskCandidateAreaVO> getProvinceByTaskId(String taskId) {
        //获取任务考生省份信息
        List<TaskCandidateArea> taskCandidateAreaList = this.lambdaQuery()
                .select(TaskCandidateArea::getAreaId, TaskCandidateArea::getName)
                .eq(TaskCandidateArea::getTaskId, taskId)
                .eq(TaskCandidateArea::getType, String.valueOf(CodeEnum.AREA_TYPE_PROVINCE.getCode()))
                .eq(TaskCandidateArea::getDelFlag, false)
                .list();
        //转换任务考生省份信息数据
        return this.convertCandidateAreaVO(taskCandidateAreaList);
    }

    @Override
    public List<TaskCandidateAreaVO> getCityById(String taskId, String province) {
        //获取任务下指定省份下的市信息
        List<TaskCandidateArea> taskCandidateAreaList = this.lambdaQuery()
                .select(TaskCandidateArea::getAreaId, TaskCandidateArea::getName)
                .eq(TaskCandidateArea::getTaskId, taskId)
                .eq(TaskCandidateArea::getType, String.valueOf(CodeEnum.AREA_TYPE_CITY.getCode()))
                .eq(TaskCandidateArea::getParentId, province)
                .eq(TaskCandidateArea::getDelFlag, false)
                .list();
        return this.convertCandidateAreaVO(taskCandidateAreaList);
    }

    /**
     * 转换任务考生区域数据
     * @param taskCandidateAreaList 任务考生区域数据
     * @return 转换后的任务考生区域数据
     */
    private List<TaskCandidateAreaVO> convertCandidateAreaVO(List<TaskCandidateArea> taskCandidateAreaList) {
        return taskCandidateAreaList.stream().map(taskCandidateArea -> {
            TaskCandidateAreaVO taskCandidateAreaVO = new TaskCandidateAreaVO();
            BeanUtils.copyProperties(taskCandidateArea, taskCandidateAreaVO);
            return taskCandidateAreaVO;
        }).collect(Collectors.toList());
    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public void importCandidateAreaByBm(MultipartFile file, String taskId) throws KqException, IOException {
        //1.如果有数据，则不允许导入了
        Integer count = lambdaQuery()
                .eq(TaskCandidateArea::getTaskId,taskId)
                .eq(TaskCandidateArea::getDelFlag,false)
                .count();
        if (count > 0 ) {
            throw new KqException(ResponseCode.ERROR_INIT_CANDIDATE_TASK_AREA_EXIST.getCode(),ResponseCode.ERROR_INIT_CANDIDATE_TASK_AREA_EXIST.getMsg());
        }

        //2.读取excel文件
        CandidateBmAreaListener candidateBmAreaListener = new CandidateBmAreaListener();
        EasyExcel.read(file.getInputStream(), CandidateBmAreaSheet.class, candidateBmAreaListener)
                .sheet().doRead();

        List<CandidateBmAreaSheet> candidateBmAreaSheetsList = candidateBmAreaListener.getDataList();

        //3.组装数据库
        List<TaskCandidateArea> taskCandidateAreaList = new ArrayList<>();
        candidateBmAreaSheetsList.stream().forEach(candidateBmAreaSheet -> {
            TaskCandidateArea taskCandidateArea = new TaskCandidateArea();
            BeanUtils.copyProperties(candidateBmAreaSheet,taskCandidateArea);
            taskCandidateArea.setTaskId(taskId)
                    .setDelFlag(false)
                    .setId(UUIDUtils.newSortUUID());
            taskCandidateAreaList.add(taskCandidateArea);
        });

        //保存机构考生区域数据
        this.saveBatch(taskCandidateAreaList);
    }

    @Override
    public List<CandidateAreaListVO> getAreaList(String taskId, Integer type, String parentId) {
        List<TaskCandidateArea> taskCandidateAreaList = this.lambdaQuery()
                .select(TaskCandidateArea::getAreaId, TaskCandidateArea::getName)
                .eq(TaskCandidateArea::getTaskId, taskId)
                .eq(TaskCandidateArea::getType, String.valueOf(type))
                .eq(StringUtils.isNotBlank(parentId), TaskCandidateArea::getParentId, parentId)
                .eq(TaskCandidateArea::getDelFlag, Boolean.FALSE)
                .orderByAsc(TaskCandidateArea::getAreaId)
                .list();
        return taskCandidateAreaList.stream().map(taskCandidateArea -> {
            CandidateAreaListVO candidateAreaListVO = new CandidateAreaListVO();
            BeanUtils.copyProperties(taskCandidateArea, candidateAreaListVO);
            return candidateAreaListVO;
        }).collect(Collectors.toList());
    }

	@Override
	public List<TaskCandidateArea> listByTaskIdAndAreaIds(String taskId, List<String> areaIds) {
		 return this.lambdaQuery()
	                .eq(TaskCandidateArea::getTaskId, taskId)
	                .in(TaskCandidateArea::getAreaId, areaIds)
	                .eq(TaskCandidateArea::getDelFlag, Boolean.FALSE)
	                .list();
	}

    /***
     * 根据taskid和区域id获取考生区域列表
     * @param taskId  任务id
     * @param areaId  区域id集合
     * @return
     */
    @Override
    public TaskCandidateArea listByTaskIdAndAreaId(String taskId, String areaId) {
        //判断是否为自己定义过的
        return this.lambdaQuery()
                .eq(TaskCandidateArea::getTaskId, taskId)
                .eq(TaskCandidateArea::getAreaId, areaId)
                .eq(TaskCandidateArea::getDelFlag, Boolean.FALSE)
                .last("LIMIT 1")
                .one();

    }


    @Override
    //@Cacheable(value = "candidate:area:tree", key = "#taskId", sync = true)
    public List<Tree> allTree(String taskId, String type) {
        if (Objects.equals(type, "origin")) {
            List<Tree> disOrderTrees = this.listPtAllArea()
                    .stream()
                    .map(area -> new Tree()
                            .setId(area.getAreaId())
                            .setPid(String.valueOf(area.getParentId()))
                            .setText(area.getName()))
                    .collect(Collectors.toList());
            return this.treeToMultilevel(disOrderTrees);
        }

        List<Tree> disOrderTrees = this.listByAreaParentId(null, taskId)
                .stream()
                .map(area -> new Tree()
                        .setId(area.getAreaId())
                        .setPid(String.valueOf(area.getParentId()))
                        .setText(area.getName()))
                .collect(Collectors.toList());
        return this.treeToMultilevel(disOrderTrees);
    }


    private List<TaskCandidateArea> listByAreaParentId(Integer areaId,String taskId) {
        return this.lambdaQuery()
                .eq(Objects.nonNull(areaId), TaskCandidateArea::getParentId, areaId)
                .eq(TaskCandidateArea::getTaskId,taskId)
                .eq(TaskCandidateArea::getDelFlag, Boolean.FALSE)
                .orderByAsc(TaskCandidateArea::getType,TaskCandidateArea::getAreaId)
                .list();
    }

    private List<TaskArea> listPtAllArea() {
        List<TaskArea> response = iOfficeAreaService.getAllAreaList();
        return response;
    }


    private   List<Tree> treeToMultilevel(List<Tree> trees) {
        Boolean loop = true;
        while (loop) {
            loop = false;
            for (int i = trees.size() - 1; i >= 0; i--) {
                String pid = trees.get(i).getPid();
                if (pid != null) {
                    String id = trees.get(i).getId();
                    int pIndex = -1;
                    Boolean noSon = true;
                    for (int j = 0; j < trees.size(); j++) {
                        if (trees.get(j).getPid() != null && trees.get(j).getPid().equals(id)) {
                            noSon = false;
                            break;
                        }
                        if (trees.get(j).getId().equals(pid)) {
                            pIndex = j;
                        }
                    }
                    if (noSon) {
                        if (pIndex >= 0) {
                            if (trees.get(pIndex).getChildren() == null) {
                                List<Tree> children = new ArrayList<Tree>();
                                trees.get(pIndex).setChildren(children);
                            }
                            trees.get(pIndex).getChildren().add(0, trees.get(i));
                            trees.remove(i);
                        }
                    } else {
                        loop = true;
                    }
                }
            }
        }
        return trees;
    }

    //判断考生区域是否有自己定义的
   /* private Boolean isSelfCandiateArea(String taskId){
        LambdaQueryWrapper<TaskCandidateArea> areaQuery = Wrappers.lambdaQuery();
        areaQuery.eq(TaskCandidateArea::getTaskId,taskId).eq(TaskCandidateArea::getDelFlag,Boolean.FALSE);
        List<TaskCandidateArea> allAreas = this.list(areaQuery);
        //判断一下是否没有自己定义区域信息
        Boolean isSelf = Boolean.TRUE;
        if(CollectionUtils.isEmpty(allAreas)){
            return isSelf;
        }
        List<String> allIds = TaskCandidateAreaVirtualAreaIdEnums.getAllIds();
        if(allAreas.size() == 4){
            for(TaskCandidateArea area : allAreas){
                if(!allIds.contains(area.getAreaId())){
                    isSelf = Boolean.FALSE;
                    break;
                }
            }
        } else {
            isSelf = Boolean.FALSE;
        }
        //return isSelf;
        return Boolean.TRUE;
    }*/

    @Override
    public String getAreaFullName(String taskId, String district) {
        StringBuilder sb = new StringBuilder();
        TaskCandidateArea d = this.lambdaQuery().eq(TaskCandidateArea::getTaskId, taskId).eq(TaskCandidateArea::getAreaId, district).eq(BaseEntity::getDelFlag, false).last("limit 1").one();
        if(Objects.nonNull(d)) {
            sb.append("/" + d.getName());
            TaskCandidateArea c = this.lambdaQuery().eq(TaskCandidateArea::getTaskId, taskId).eq(TaskCandidateArea::getAreaId, d.getParentId()).eq(BaseEntity::getDelFlag, false).last("limit 1").one();
            if(Objects.nonNull(c)) {
                sb.insert(0, "/" + c.getName());
                TaskCandidateArea p = this.lambdaQuery().eq(TaskCandidateArea::getTaskId, taskId).eq(TaskCandidateArea::getAreaId, c.getParentId()).eq(BaseEntity::getDelFlag, false).last("limit 1").one();
                if(Objects.nonNull(c)) {
                    sb.insert(0, p.getName());
                }
            }
        }

        return sb.toString();
    }

    /**
     * 判断考生区域入库是否已经存，存在不入，不存在入
     * @param areas
     * @return
     */
    public Boolean saveAreaWhenIsExists(String taskId,List<TaskCandidateArea> areas){
        List<TaskCandidateArea> entitys = new ArrayList<>(areas.size());
        for(TaskCandidateArea area : areas){
            LambdaQueryWrapper<TaskCandidateArea> query = Wrappers.lambdaQuery();
            query.eq(TaskCandidateArea::getTaskId,taskId)
                    .eq(TaskCandidateArea::getAreaId,area.getAreaId())
                    .eq(TaskCandidateArea::getDelFlag,Boolean.FALSE);
            if(this.count(query) < 1){
                entitys.add(area);
            }
        }
        if(CollectionUtils.isEmpty(entitys)){
            return Boolean.TRUE;
        }
        return this.saveBatch(entitys);
    }
}
